// 多线程的应用
// Created by Administrator on 2025/6/20.
//

#include <iostream>
#include <mutex>
#include <thread>
using namespace std;

void printMsg(int num) {
    for (int i = 0; i < num; i++) {
        cout << "learn thread." << endl;
        _sleep(500);
    }
}

void joinFunc() {
    thread t1(printMsg, 5);
    // 等待t1线程执行结束
    t1.join();
    cout << "this is main thread msg." << endl;
}

void detachFunc() {
    thread t2(printMsg, 5);
    // 线程分离，t2后台执行
    t2.detach();
    for (int i = 0; i < 5; i++) {
        cout << "this is main thread msg." << endl;
        _sleep(500);
    }
}

class PrintTask {
public:
    void operator()(int count) const {
        for (int i = 0; i < count; i++) {
            cout << "hello from thread (function object)." << endl;
        }
    }
};

void objectFunc() {
    // 调用函数对象
    thread t3(PrintTask(), 5);
    t3.join();
    cout << "thread object function execute end." << endl;
}

/**
 * lambda 写法
 */
void lambdaFunc() {
    thread t4([](int count) {
        for (int i = 0; i < count; ++i) {
            cout << "thread lambda function" << endl;
        }
    }, 5);
    t4.join();
}

/**
 * 多线程参数引用传递
 * @param num
 */
void refValueFunc(int &num) {
    for (int i = 0; i < 5; i++) {
        num++;
    }
}

/**
 * 互斥锁
 * 防止多个线程同时访问共享资源造成数据混乱。
 * 当多个线程同时访问共享资源时，它首先会被锁住，只有获取到锁的线程才能访问共享资源，其它线程会被阻塞，只有当获取锁的线程释放锁后才能再次获取锁。
 */

mutex mtx;

void safeFunc(int num) {
    mtx.lock(); // 锁定
    cout << "num:" << num << endl;
    mtx.unlock(); // 解锁
}

void mtxFunc() {
    for (int i = 0; i < 10; ++i) {
        thread t1(safeFunc, i);
        t1.detach();
    }
    cout << "end" << endl;
}

/**
 * C++ 锁
 * 用于简化互斥锁的使用，可以自动获取锁及释放锁。
 *
 * lock_guard 作用域锁，当构造时自动锁定互斥变量，析构时自动释放互斥变量。
 * unique_lock 和 lock_guard 类似，但提供了更多灵活性，如：可以手动释放锁。
 */


void lockGuardFunc(int num) {
    lock_guard<mutex> lg(mtx);
    cout << num << endl;
}

void guardImplFunc() {
    for (int i = 0; i < 10; ++i) {
        thread t1(lockGuardFunc, i);
        t1.detach();
    }
    cout << "end" << endl;
}


int main(int argc, char *argv[]) {
    // joinFunc();
    // detachFunc();
    // objectFunc();
    // lambdaFunc();
    // mtxFunc();
    guardImplFunc();
    return 0;
}
